#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <event2/buffer.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#define DEFAULT_PORT 8080
#define RESP_HEADER_FMT "HTTP/1.1 200 OK\r\n" \
                         "Content-Type: text/html\r\n" \
                         "Content-Length: %zu\r\n" \
                         "Connection: close\r\n\r\n"

static char *response_data = NULL;
static size_t response_len = 0;

/* 信号处理回调 */
static void signal_cb(evutil_socket_t sig, short events, void *user_data) {
    struct event_base *base = reinterpret_cast<event_base *>(user_data);
    printf("Caught signal %d, shutting down...\n", sig);
    event_base_loopexit(base, NULL);
}

/* 事件回调：处理连接事件 */
static void event_cb(struct bufferevent *bev, short events, void *ctx) {
    if (events & BEV_EVENT_ERROR) {
        perror("Bufferevent error");
    }
    bufferevent_free(bev);
}

/* 写回调：数据发送完成后关闭连接 */
static void write_cb(struct bufferevent *bev, void *ctx) {
    struct evbuffer *output = bufferevent_get_output(bev);
    if (evbuffer_get_length(output) == 0) {
        bufferevent_free(bev);
    }
}

/* 接受新连接回调 */
static void accept_conn_cb(struct evconnlistener *listener,
    evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx) {
    struct event_base *base = evconnlistener_get_base(listener);
    struct bufferevent *bev = bufferevent_socket_new(base, fd, 
        BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
    
    if (!bev) {
        fprintf(stderr, "Error creating bufferevent!");
        return;
    }

    bufferevent_setcb(bev, NULL, write_cb, event_cb, NULL);
    bufferevent_enable(bev, EV_WRITE);
    bufferevent_disable(bev, EV_READ);

    /* 发送预生成的响应数据 */
    bufferevent_write(bev, response_data, response_len);
}

/* 初始化HTTP响应数据 */
static int init_response(const char *filename) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        perror("Failed to open HTML file");
        return -1;
    }

    /* 获取文件大小 */
    if (fseek(fp, 0, SEEK_END)) {
        perror("fseek failed");
        fclose(fp);
        return -1;
    }
    long fsize = ftell(fp);
    if (fsize == -1) {
        perror("ftell failed");
        fclose(fp);
        return -1;
    }
    rewind(fp);

    /* 读取文件内容 */
    char *content = reinterpret_cast<char *>(malloc(fsize));
    if (!content) {
        perror("malloc failed");
        fclose(fp);
        return -1;
    }
    if (fread(content, 1, fsize, fp) != (size_t)fsize) {
        perror("fread failed");
        free(content);
        fclose(fp);
        return -1;
    }
    fclose(fp);

    /* 生成HTTP响应头 */
    char header[512];
    int header_len = snprintf(header, sizeof(header), RESP_HEADER_FMT, fsize);
    if (header_len < 0 || header_len >= (int)sizeof(header)) {
        fprintf(stderr, "Header generation failed");
        free(content);
        return -1;
    }

    /* 合并头和内容 */
    response_len = header_len + fsize;
    response_data = reinterpret_cast<char *>(malloc(response_len));
    if (!response_data) {
        perror("malloc failed");
        free(content);
        return -1;
    }

    memcpy(response_data, header, header_len);
    memcpy(response_data + header_len, content, fsize);
    free(content);

    return 0;
}

/* 清理资源 */
static void cleanup() {
    if (response_data) {
        free(response_data);
        response_data = NULL;
    }
}

int main(int argc, char **argv) {
    /* 初始化响应数据 */
    if (init_response("screen.html") != 0) {
        return EXIT_FAILURE;
    }

    /* 初始化libevent */
    struct event_base *base = event_base_new();
    if (!base) {
        fprintf(stderr, "Could not initialize libevent!\n");
        cleanup();
        return EXIT_FAILURE;
    }

    /* 设置信号处理 */
    struct event *sigint = evsignal_new(base, SIGINT, signal_cb, base);
    if (!sigint || event_add(sigint, NULL) < 0) {
        fprintf(stderr, "Could not create/add signal event!\n");
        event_base_free(base);
        cleanup();
        return EXIT_FAILURE;
    }

    /* 配置监听地址 */
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(0);  // 0.0.0.0
    sin.sin_port = htons(DEFAULT_PORT);

    /* 创建监听器 */
    struct evconnlistener *listener = evconnlistener_new_bind(
        base, accept_conn_cb, base,
        LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
        (struct sockaddr*)&sin, sizeof(sin));
    if (!listener) {
        perror("Couldn't create listener");
        event_base_free(base);
        cleanup();
        return EXIT_FAILURE;
    }

    printf("Server running on port %d...\n", DEFAULT_PORT);
    event_base_dispatch(base);

    /* 清理 */
    evconnlistener_free(listener);
    event_free(sigint);
    event_base_free(base);
    cleanup();

    return EXIT_SUCCESS;
}